let editDiv = null; //编辑元素
let range = ""; //选区
export default {
  title:"messageTemplate案例",
  data() {
    return {
      itemInfo:{
        '${customerNickname}':'客户昵称',
        '${affiliatedConsultant}':'所属顾问',
        '${department}':'所属部门'
      },
      // 初始化赋值
      innerHtml: "", 
      //备份数据
      innerHtmlBf: "", 
      // 实时html-动态变量
      nowHtmlT: "", 
      // 实时文本
      // nowText: "", 
      // 获取当前最新数据
      getDataTime: 1000,
      getDataTimeInter: null,
      textSize: 0,
      maxNum: 500,
      isInspection: false,
      uploadHtml: true
    };
  },
  mounted() {
    this.initEditFun();
  },
  methods: {
    initEditFun() {
      editDiv = document.getElementById("editSelDiv");
      // 这一步是保留住edit编辑框中的选区的范围对象。
      // 否则失焦后，getSelection()方法返回的选区对象已经不再是编辑框了，已经获取不到编辑框中的范围对象了。
      editDiv.addEventListener("blur", () => {
        range = window.getSelection() ? window.getSelection().getRangeAt(0) : "";
      });
      document.addEventListener("selectionchange", e => {
        let selection = document.getSelection();
        let rangeVal = selection && selection.rangCount > 0 ? selection.getRangeAt(0) : "";
        if(rangeVal && this.hasAncestorWithId(rangeVal.commonAncestorContainer, "editSelDiv")) {
          range = window.getSelection() ? window.getSelection().getRangeAt(0) : "";
        }
      });
    },

    /**
     * 递归判断是否有父级id
     * @param {*} element 
     * @param {*} id 
     * @returns 
     */
    hasAncestorWithId(element, id) {
      if (!element) return false;
      if (element.id === id) return true;
      if (element.parentNode) {
        return this.hasAncestorWithId(element.parentNode, id);
      }
      return false;
    },

    /**
     * 编辑输入
     * @param {*} e 
     */
    editInput(e) {
      //获取最新内容
      this.getNowContent(); 
      if (e.target.children.length > 0) { this.judgeSpanClass(); }
      if (e.target.innerText == "") {
        range = "";
        e.target.innerHtml = "";
        this.innerHtml = "";
        this.innerHtmlBf = "";
      }
    },
    
    /**
     * 判断span的class样式 
     * 当值不在是设定值时,切换class名
     */
    judgeSpanClass() {
      let valueList = [];
      $.each(this.itemInfo,(key,value)=>{
        valueList.push(value);
      })
      // 遍历span的值，比较先有的数据集合value,如果匹配，则追加样式，不匹配则去掉样式
      let spanAll = document.querySelectorAll(".edit span");
      spanAll.forEach(item => {
        let nowVal = item.childNodes[0].data;
        if(nowVal){
          item.className = valueList.includes(nowVal) ? "selColor" : "mrClass";
        }
      });
    },

    /**
     * 纯文本粘贴
     * @param {*} e 
     */
    handlePaste(e) {
      e.preventDefault(); // 阻止默认粘贴操作
      const clipboardData = e.clipboardData || window.clipboardData;
      const text = clipboardData.getData("text/plain"); // 获取纯文本内容
      document.execCommand("insertHTML", false, text); // 将文本插入 contenteditable 元素中
    },

    /**
     * 添加按钮
     * @param {*} Text 
     * @returns 
     */
    addStrBtnFun(Text) {
      const innerText = this.$refs.editInput.innerText;
      const now_length = innerText.split("\u200B").join("").length;
      const length = now_length + Text.length; //当前长度+按钮文字长度
      if (length > this.maxNum) {
        return;
      }
      const span = document.createElement("span");
      span.innerText = Text;
      span.className = "selColor";
      // 如果在页面刷新再点击编辑框之前就点击了按钮，此时range中并没有选区范围对象
      if (range === "") {
        let selection = window.getSelection();
        selection.selectAllChildren(editDiv);
        // selectAllChildren把指定元素的所有子元素设为选中区域，并取消之前的选中区域。不包括node节点本身。
        /*
          Selection.collapseToEnd() 方法的作用是取消当前选区，并把光标定位在原选区的最末尾处，如果此时光标所处的位置是可编辑的，且它获得了焦点，则光标会在原地闪烁。
          以上selectAllChildren方法，将div中子节点全部选中，collapseToEnd方法将选中区域取消，并且将光标定位到原区的末尾。
        */
        selection.collapseToEnd();
        range = window.getSelection() ? window.getSelection().getRangeAt(0) : ""; // 无论哪一步都需要保存当前编辑框的选区对象
      }
      let sel = window.getSelection();
      let space = document.createTextNode("\u200B"); // 创建 &ZeroWidthSpace; 实体字符节点
      range.insertNode(space);
      range.insertNode(span); // insertNode方法，在range选区开头插入一个节点
      /*
      removeAllRanges方法：删除之前的所有选区。
      这一步的意义：因为当我们点击其他区域时，选区对象已经改变，不再是编辑框中的选区对象，这时候我们接下来的操作都不会符合我们想象中的样子
     */
      sel.removeAllRanges();
      sel.addRange(range); // 这一步就是添加当前区域对象到选区对象中，所以选区对象会再次指向编辑框中的选区，不会出现别的错误操作。
      sel.collapseToEnd();

      this.judgeSpanClass();
      this.getNowContent();
    },


    /**
     * 获取到当前选中内容
     */
    resevedSelDiv() {
      range = document.createRange();
      range.selectNode(document.getElementById("editSelDiv").lastChild);
      window.getSelection().removeAllRanges();
      window.getSelection().addRange(range);
      let selection = window.getSelection();
      selection.selectAllChildren(editDiv);
      selection.collapseToEnd();
      range = window.getSelection() ? window.getSelection().getRangeAt(0) : "";
    },

    // 获取最新的内容
    getNowContent() {
      const innerText = this.$refs.editInput.innerText;
      const length = innerText.split("\u200B").join("").length;
      if (length <= this.maxNum) {
        this.innerHtmlBf = this.$refs.editInput.innerHTML;
        // this.nowText = this.$refs.editInput.innerText;
        this.textSize = length;
        this.isInspection = false;
      } else {
        this.uploadHtml = false;
        this.$nextTick(() => {
          this.innerHtml = this.innerHtmlBf;
          this.uploadHtml = true;
          setTimeout(() => {
            this.resevedSelDiv();
          }, 1);
        });
      }
    },
    
    /**
     * 获取内置模板内容
     */
    getSpecialContent() {
      let spanAll = document.querySelectorAll(".edit span");
      let mrArr = [];
      spanAll.forEach(item => {
        let nowVal = item.childNodes[0].data;
        mrArr.push(nowVal);
        // 寻找span中 class为 selColor 的项,将他的 data 换成对应的内置模板内容
        if (item.className == "selColor") {
          $.each(this.itemInfo,(key,value)=>{
            if (nowVal == value) {
              item.childNodes[0].data = key;
            }
          })
        }
        // if (item.className == "selColor") {
        //   if (nowVal == this.addBtnText) {
        //     item.childNodes[0].data = "${customerNickname}"; //客户昵称
        //   } else if (nowVal == this.serviceConsultant) {
        //     item.childNodes[0].data = "${affiliatedConsultant}"; //所属顾问
        //   } else if (nowVal == this.departments) {
        //     item.childNodes[0].data = "${department}"; //所属部门
        //   }
        // }
      });
      this.nowHtmlT = this.$refs.editInput.innerText;
      // this.nowHtmlT = this.replaceText(this.nowHtmlT, this.addBtnText, "${customerNickname}");
      // this.nowHtmlT = this.replaceText(this.nowHtmlT, this.serviceConsultant, "${affiliatedConsultant}");
      // this.nowHtmlT = this.replaceText(this.nowHtmlT, this.departments, "${department}");
      spanAll.forEach((item, i) => {
        item.childNodes[0].data = mrArr[i];
      });
      this.$emit("nowHtmlT", this.nowHtmlT);
    },

    /**
     * 替换文本
     * @param {*} text 
     * @param {*} oldStr 
     * @param {*} newStr 
     * @returns 
     */
    replaceText(text, oldStr, newStr) {
      // 检查是否为字符串类型
      if (typeof text !== "string") {
        text = String(text);
      }
      // 替换字符
      text = text.replace(new RegExp(oldStr, "g"), newStr);
      // 处理子级
      if (text.includes("<") && text.includes(">")) {
        const start = text.indexOf("<");
        const end = text.indexOf(">") + 1;
        let subtext = text.substring(start, end);
        while (start >= 0 && end >= 0 && end > start) {
          const subtextNew = replaceText(subtext, oldStr, newStr);
          text = text.substring(0, start) + subtextNew + text.substring(end);
          subtext = text.substring(start, end);
        }
      }
      return text;
    },

    /**
     * 检查是否为空
     */
    checkIsNonData() {
      const innerText = this.$refs.editInput.innerText;
      const length = innerText.split("\u200B").join("").length;
      if (innerText == "" || innerText == "\n" || length == 0) {
        this.isInspection = true;
      } else {
        this.isInspection = false;
      }
    },

    /**
     *  清空选框
     */
    clearTextBox(){
      editDiv = document.getElementById("editSelDiv");
      editDiv.innerHTML = ''
      this.nowHtmlT = ''
      // this.nowText = ''
    }
  },
  beforeDestroy() {
    editDiv = null; //编辑元素
    range = ""; //选区
  }
};
